home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / cross / devpic.lha / devpic / source / picasm / config.c next >
C/C++ Source or Header  |  2000-02-27  |  7KB  |  299 lines

  1. /*
  2.  * picasm -- config.c
  3.  *
  4.  * handles configuration fuse setting with the CONFIG-directive
  5.  *
  6.  * Timo Rossi <trossi@iki.fi>
  7.  * 
  8.  */
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12.  
  13. #include "picasm.h"
  14.  
  15. /*
  16.  * Check Yes/No (or Disable(d)/Enable(d) or On/Off) strings for CONFIG
  17.  *
  18.  * returns: 0=no, 1=yes, -1=error
  19.  *
  20.  */
  21. static int
  22. config_yes_no(char *s)
  23. {
  24.   if(strcasecmp(s, "yes") == 0 || strcasecmp(s, "on") == 0 ||
  25.      strncasecmp(s, "enable", 6) == 0)
  26.     return 1;
  27.   else if(strcasecmp(s, "no") == 0 || strcasecmp(s, "off") == 0 ||
  28.       strncasecmp(s, "disable", 7) == 0)
  29.     return 0;
  30.   else
  31.     return -1; /* error */
  32. }
  33.  
  34. /*
  35.  * selstr consists of NUL-terminated strings with two NULs in the end
  36.  * If str matches one of the components of selstr, the index of
  37.  * that component (starting from zero) is returned,
  38.  * if no match is found, -1 is returned.
  39.  */
  40. static int
  41. strsel(char *selstr, char *str)
  42. {
  43.   int sel = 0;
  44.  
  45.   while(*selstr != '\0') {
  46.     if(strcasecmp(selstr, str) == 0)
  47.       return sel;
  48.  
  49.     selstr += strlen(selstr)+1;
  50.     sel++;
  51.   }
  52.  
  53.   return -1;
  54. }
  55.  
  56. /*
  57.  * parse the CONFIG directive
  58.  * 
  59.  * (the separate code protections of PIC14000 are not currently,
  60.  *  and neither are the partial protections on some PICs)
  61.  * 
  62.  */
  63. void
  64. parse_config(void)
  65. {
  66.   static char symname[256];
  67.   int t;
  68.  
  69.   for(;;) {
  70.     if(token_type != TOK_IDENTIFIER) {
  71. cfg_error:
  72.       error(1, "CONFIG syntax error");
  73.       return;
  74.     }
  75.     strcpy(symname, token_string);
  76.     get_token();
  77.  
  78.     /* hmm... this is a little kludge, but as
  79.        the tokenizer now makes 'local id's from
  80.        the valid config strings, this must be used... */
  81.     if(token_type != TOK_LOCAL_ID) {
  82.       if(token_type != TOK_EQUAL) {
  83.     error(1, "'=' expected");
  84.     return;
  85.       }
  86.       get_token();
  87.       if(token_type != TOK_IDENTIFIER)
  88.     goto cfg_error;
  89.     }
  90.  
  91.     switch(strsel("OSC\0WDT\0CP\0PWRT\0MCLR\0BOD\0MPE\0", symname)) {
  92.       case 0: /* OSC */
  93.         if((t = strsel("LP\0XT\0HS\0RC\0INTRC\0INTRC_CLKOUT\0"
  94.                "EXTRC\0EXTRC_CLKOUT\0IN\0", token_string)) < 0)
  95.       goto cfg_error;
  96.  
  97.     switch(pic_type->fusetype) {
  98.       case FUSE_12C5XX:
  99.         if(t >= 2 && t != 4 && t != 6) {
  100.           error(1, "Invalid oscillator type %s for PIC%s",
  101.             token_string, pic_type->name);
  102.           return;
  103.         }
  104.         if(t >= 2)
  105.            t >>= 2;
  106.         config_fuses = (config_fuses & 0xffc) | t;
  107.         break;
  108.         
  109.       case FUSE_12C6XX:
  110.         if(t == 3 || t >= 8) {
  111.           error(1, "Invalid oscillator type %s for PIC%s",
  112.             token_string, pic_type->name);
  113.           return;
  114.         }
  115.         config_fuses = (config_fuses & 0x3ff8) | t;
  116.         break;
  117.     
  118.       case FUSE_14000:
  119.         if(t != 2 && t != 4 && t != 8) { /* accept both IN and INTRC */
  120.           error(1, "Invalid oscillator type %s for PIC%s",
  121.             token_string, pic_type->name);
  122.           return;
  123.         }
  124.         config_fuses = (config_fuses & 0x3ffe) | (t != 2);
  125.         break;
  126.  
  127.       case FUSE_16C5X:
  128.       case FUSE_16F8X:
  129.       case FUSE_16CXX1:
  130.       case FUSE_16CXX2:
  131.       case FUSE_16C55X:
  132.       case FUSE_16C62X:
  133.       case FUSE_16C6XA:
  134.       case FUSE_16C71X:
  135.       case FUSE_16C715:
  136.         if(t >= 4) {
  137.           error(1, "Invalid oscillator type %s for PIC%s",
  138.             token_string, pic_type->name);
  139.           return;
  140.         }
  141.         config_fuses = (config_fuses & 0x3ffc) | t;
  142.         break;
  143.         }
  144.     break;
  145.  
  146.       case 1: /* WDT - watchdog timer */
  147.     if((t = config_yes_no(token_string)) < 0)
  148.       goto cfg_error;
  149.  
  150.     switch(pic_type->fusetype) {
  151.       case FUSE_12C6XX:
  152.         config_fuses = (config_fuses & 0x3ff7) | (t ? 8 : 0);
  153.         break;
  154.         
  155.       default:
  156.         config_fuses = (config_fuses & 0x3ffb) | (t ? 4 : 0);
  157.         break;
  158.         }
  159.     break;
  160.         
  161.       case 2: /* CP - code protect */
  162.             /* partial protection is not supported */
  163.     if((t = config_yes_no(token_string)) < 0)
  164.       goto cfg_error;
  165.     
  166.     switch(pic_type->fusetype) {
  167.       case FUSE_16C5X:
  168.       case FUSE_12C5XX:
  169.         config_fuses = (config_fuses & 0xff7) | (t ? 0 : 8);
  170.         break;
  171.         
  172.       case FUSE_12C6XX:
  173.         config_fuses = (config_fuses & 0x009f) | (t ? 0 : 0x3f60);
  174.         break;
  175.                 
  176.       case FUSE_16CXX1: /* 1 code protect bit */
  177.         config_fuses = (config_fuses & 0x3fef) | (t ? 0 : 0x10);
  178.         break;
  179.         
  180.       case FUSE_16CXX2: /* 2 code protect bits */
  181.         config_fuses = (config_fuses & 0x3fcf) | (t ? 0 : 0x30);
  182.         break;
  183.         
  184.       case FUSE_16F8X:
  185.         config_fuses = (config_fuses & 0x000f) | (t ? 0 : 0x3ff0);
  186.         break;
  187.         
  188.       case FUSE_16C71X:
  189.         config_fuses = (config_fuses & 0x004f) | (t ? 0 : 0x3fb0);
  190.         break;
  191.         
  192.       case FUSE_16C6XA:
  193.       case FUSE_16C62X: /* 2 code protect bits, replicated */
  194.       case FUSE_16C55X:
  195.       case FUSE_16C715:
  196.         config_fuses = (config_fuses & 0x00cf) | (t ? 0 : 0x3f30);
  197.         break;
  198.         
  199.       case FUSE_14000:
  200.         config_fuses = (config_fuses & 0x3f4f) | (t ? 0 : 0x00b0);
  201.         break;
  202.         }
  203.     break;
  204.  
  205.       case 3: /* PWRT - power-up timer */
  206.     if((t = config_yes_no(token_string)) < 0)
  207.       goto cfg_error;
  208.     
  209.     switch(pic_type->fusetype) {
  210.       case FUSE_16CXX1:
  211.       case FUSE_16CXX2:
  212.         config_fuses = (config_fuses & 0x3ff7) | (t ? 8 : 0);
  213.         break;
  214.         
  215.       case FUSE_16C6XA:
  216.       case FUSE_16C55X:
  217.       case FUSE_16F8X:
  218.       case FUSE_16C71X:
  219.       case FUSE_16C715:
  220.       case FUSE_16C62X:
  221.       case FUSE_14000:
  222.         config_fuses = (config_fuses & 0x3ff7) | (t ? 0 : 8);
  223.         break;
  224.  
  225.       case FUSE_12C6XX:
  226.         config_fuses = (config_fuses & 0x3fef) | (t ? 0 : 0x10);
  227.         break;
  228.         
  229.       case FUSE_16C5X:
  230.       case FUSE_12C5XX:
  231.         error(1, "No power-up timer in PIC%s", pic_type->name);
  232.         return;
  233.     }
  234.     break;
  235.  
  236.       case 4: /* MCLR - enable/disable MCLR (8-pin PICs) */
  237.     if((t = config_yes_no(token_string)) < 0)
  238.       goto cfg_error;
  239.         
  240.     switch(pic_type->fusetype) {
  241.           case FUSE_12C5XX:
  242.         config_fuses = (config_fuses & 0xfef) | (t ? 0x10 : 0);
  243.         break;
  244.         
  245.           case FUSE_12C6XX:
  246.         config_fuses = (config_fuses & 0x3f7f) | (t ? 0x80 : 0);
  247.         break;
  248.         
  249.           default:
  250.         error(1,"No MCLRE in PIC%s", pic_type->name);
  251.         return;
  252.         }
  253.     break;
  254.         
  255.       case 5: /* BOD - brown-out detect */
  256.     if((t = config_yes_no(token_string)) < 0)
  257.       goto cfg_error;
  258.         
  259.     switch(pic_type->fusetype) {
  260.       case FUSE_16C62X:
  261.       case FUSE_16C6XA:
  262.       case FUSE_16C71X:
  263.       case FUSE_16C715:
  264.         config_fuses = (config_fuses & 0x3fbf) | (t ? 0x40 : 0);
  265.         break;
  266.         
  267.           default:
  268.         error(1,"No BODEN in PIC%s", pic_type->name);
  269.         return;
  270.     }
  271.     break;
  272.         
  273.       case 6: /* MPE - memory parity error */
  274.     if((t = config_yes_no(token_string)) < 0)
  275.       goto cfg_error;
  276.         
  277.     switch(pic_type->fusetype) {
  278.       case FUSE_16C715:
  279.         config_fuses = (config_fuses & 0x3f7f) | (t ? 0x80 : 0);
  280.         break;
  281.         
  282.       default:
  283.         error(1,"No MPEEN in PIC%s", pic_type->name);
  284.         return;
  285.     }
  286.     break;
  287.         
  288.       default:
  289.     goto cfg_error;
  290.     }
  291.       
  292.     get_token();
  293.     if(token_type != TOK_COMMA)
  294.       break;
  295.  
  296.     get_token();
  297.   }
  298. }
  299.